//! 策略模块
//! 
//! 提供一些策略的编写案例，以 trader_ 开头的是择时交易策略案例

use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};
use crate::objects::{
    bar::{RawBar, NewBar},
    enums::{Direction, Freq, Mark, Operate},
    signal::Signal,
};
use chrono::Datelike;
use crate::utils::bar_generator::BarGenerator;
use crate::traders::base::CzscTrader;

/// 策略基础特征
pub trait CzscStrategyBase {
    /// 交易标的
    fn symbol(&self) -> &str;
    
    /// 所有持仓策略中的交易信号列表
    fn unique_signals(&self) -> Vec<String>;
    
    /// 交易信号参数配置
    fn signals_config(&self) -> HashMap<String, serde_json::Value>;
    
    /// K线周期列表
    fn freqs(&self) -> Vec<Freq>;
    
    /// 排好序的 K 线周期列表
    fn sorted_freqs(&self) -> Vec<Freq> {
        let mut freqs = self.freqs();
        freqs.sort();
        freqs
    }
    
    /// 基础 K 线周期
    fn base_freq(&self) -> Freq {
        self.sorted_freqs()[0]
    }
    
    /// 持仓策略列表
    fn positions(&self) -> Vec<Position>;
    
    /// 使用策略定义初始化一个 BarGenerator 对象
    fn init_bar_generator(&self, bars: &[RawBar], kwargs: &HashMap<String, serde_json::Value>) -> (BarGenerator, Vec<RawBar>) {
        let base_freq = self.base_freq();
        let sorted_freqs = self.sorted_freqs();
        
        // 检查是否传入了已初始化的BarGenerator
        if let Some(bg_json) = kwargs.get("bg") {
            // TODO: 实现从JSON恢复BarGenerator的逻辑
            unimplemented!("从JSON恢复BarGenerator暂未实现");
        }
        
        // 创建新的BarGenerator
        let mut bg = BarGenerator::new(
            base_freq.to_string(),
            sorted_freqs.iter().map(|f| f.to_string()).collect(),
            1000,
            "A".to_string(),
        );
        
        // 获取初始化参数
        let sdt = kwargs.get("sdt").and_then(|v| v.as_str()).map(|s| {
            DateTime::parse_from_rfc3339(s).unwrap_or_else(|_| Utc::now().into())
        });
        let n = kwargs.get("n").and_then(|v| v.as_u64()).unwrap_or(100) as usize;
        
        // 初始化BarGenerator
        let init_bars = if let Some(start_dt) = sdt {
            bars.iter()
                .filter(|bar| bar.dt >= start_dt)
                .take(n)
                .cloned()
                .collect::<Vec<_>>()
        } else {
            bars.iter().take(n).cloned().collect::<Vec<_>>()
        };
        
        for bar in &init_bars {
            bg.update(bar.clone());
        }
        
        // 返回剩余的K线数据
        let remaining_bars = bars.iter()
            .skip(init_bars.len())
            .cloned()
            .collect::<Vec<_>>();
        
        (bg, remaining_bars)
    }
    
    /// 初始化交易器
    fn init_trader(&self, bars: &[RawBar], kwargs: &HashMap<String, serde_json::Value>) -> CzscTrader {
        let (bg, remaining_bars) = self.init_bar_generator(bars, kwargs);
        
        let mut trader = CzscTrader::new(
            self.symbol(),
            "策略交易员",
        );
        
        // 使用剩余K线数据初始化交易器
        // TODO: 实现交易器的update方法
        // for bar in &remaining_bars {
        //     trader.update(bar);
        // }
        
        trader
    }
    
    /// 回测
    fn backtest(&self, bars: &[RawBar], kwargs: &HashMap<String, serde_json::Value>) -> CzscTrader {
        self.init_trader(bars, kwargs)
    }
}

/// 持仓策略
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Position {
    /// 持仓名称
    pub name: String,
    /// 持仓代码
    pub code: String,
    /// 持仓方向
    pub direction: Direction,
    /// 交易信号列表
    pub signals: Vec<Signal>,
    /// 唯一信号列表
    pub unique_signals: Vec<String>,
    /// 持仓权重
    pub weight: f64,
    /// 是否启用
    pub enabled: bool,
}

impl Position {
    /// 创建新的持仓策略
    pub fn new(name: String, code: String, direction: Direction) -> Self {
        Self {
            name,
            code,
            direction,
            signals: Vec::new(),
            unique_signals: Vec::new(),
            weight: 1.0,
            enabled: true,
        }
    }
    
    /// 添加信号
    pub fn add_signal(&mut self, signal: Signal) {
        let signal_key = signal.key();
        if !self.unique_signals.contains(&signal_key) {
            self.unique_signals.push(signal_key);
        }
        self.signals.push(signal);
    }
    
    /// 设置权重
    pub fn set_weight(&mut self, weight: f64) {
        self.weight = weight;
    }
    
    /// 启用或禁用
    pub fn set_enabled(&mut self, enabled: bool) {
        self.enabled = enabled;
    }
}

/// JSON策略实现
pub struct CzscJsonStrategy {
    symbol: String,
    positions: Vec<Position>,
    signals_config: HashMap<String, serde_json::Value>,
}

impl CzscJsonStrategy {
    /// 创建新的JSON策略
    pub fn new(symbol: String, positions: Vec<Position>, signals_config: HashMap<String, serde_json::Value>) -> Self {
        Self {
            symbol,
            positions,
            signals_config,
        }
    }
}

impl CzscStrategyBase for CzscJsonStrategy {
    fn symbol(&self) -> &str {
        &self.symbol
    }
    
    fn unique_signals(&self) -> Vec<String> {
        let mut signals = Vec::new();
        for pos in &self.positions {
            signals.extend(pos.unique_signals.clone());
        }
        signals.sort();
        signals.dedup();
        signals
    }
    
    fn signals_config(&self) -> HashMap<String, serde_json::Value> {
        self.signals_config.clone()
    }
    
    fn freqs(&self) -> Vec<Freq> {
        // 从信号配置中提取频率信息
        let mut freqs = Vec::new();
        for (_, config) in &self.signals_config {
            if let Some(freq_str) = config.get("freq").and_then(|v| v.as_str()) {
                            if let Some(freq) = Freq::from_str(freq_str) {
                freqs.push(freq);
            }
            }
        }
        freqs.sort();
        freqs.dedup();
        freqs
    }
    
    fn positions(&self) -> Vec<Position> {
        self.positions.clone()
    }
}

/// 创建单均线多头策略
pub fn create_single_ma_long(symbol: &str, ma_name: &str, is_stocks: bool, kwargs: &HashMap<String, serde_json::Value>) -> Position {
    let mut pos = Position::new(
        format!("单均线多头_{}", ma_name),
        symbol.to_string(),
        Direction::Up,
    );
    
    // 添加均线信号
    let signal = Signal::new(
        "日线".to_string(),
        ma_name.to_string(),
        "多头".to_string(),
        "多头".to_string(),
        "其他".to_string(),
        "其他".to_string(),
        50,
    );
    
    pos.add_signal(signal);
    pos
}

/// 创建单均线空头策略
pub fn create_single_ma_short(symbol: &str, ma_name: &str, is_stocks: bool, kwargs: &HashMap<String, serde_json::Value>) -> Position {
    let mut pos = Position::new(
        format!("单均线空头_{}", ma_name),
        symbol.to_string(),
        Direction::Down,
    );
    
    // 添加均线信号
    let signal = Signal::new(
        "日线".to_string(),
        ma_name.to_string(),
        "空头".to_string(),
        "空头".to_string(),
        "其他".to_string(),
        "其他".to_string(),
        50,
    );
    
    pos.add_signal(signal);
    pos
}

/// 创建MACD多头策略
pub fn create_macd_long(symbol: &str, is_stocks: bool, kwargs: &HashMap<String, serde_json::Value>) -> Position {
    let mut pos = Position::new(
        "MACD多头".to_string(),
        symbol.to_string(),
        Direction::Up,
    );
    
    // 添加MACD信号
    let signal = Signal::new(
        "日线".to_string(),
        "MACD".to_string(),
        "多头".to_string(),
        "多头".to_string(),
        "其他".to_string(),
        "其他".to_string(),
        50,
    );
    
    pos.add_signal(signal);
    pos
}

/// 创建MACD空头策略
pub fn create_macd_short(symbol: &str, is_stocks: bool, kwargs: &HashMap<String, serde_json::Value>) -> Position {
    let mut pos = Position::new(
        "MACD空头".to_string(),
        symbol.to_string(),
        Direction::Down,
    );
    
    // 添加MACD信号
    let signal = Signal::new(
        "日线".to_string(),
        "MACD".to_string(),
        "空头".to_string(),
        "空头".to_string(),
        "其他".to_string(),
        "其他".to_string(),
        50,
    );
    
    pos.add_signal(signal);
    pos
}

/// 创建CCI多头策略
pub fn create_cci_long(symbol: &str, is_stocks: bool, kwargs: &HashMap<String, serde_json::Value>) -> Position {
    let mut pos = Position::new(
        "CCI多头".to_string(),
        symbol.to_string(),
        Direction::Up,
    );
    
    // 添加CCI信号
    let signal = Signal::new(
        "日线".to_string(),
        "CCI".to_string(),
        "多头".to_string(),
        "多头".to_string(),
        "其他".to_string(),
        "其他".to_string(),
        50,
    );
    
    pos.add_signal(signal);
    pos
}

/// 创建CCI空头策略
pub fn create_cci_short(symbol: &str, is_stocks: bool, kwargs: &HashMap<String, serde_json::Value>) -> Position {
    let mut pos = Position::new(
        "CCI空头".to_string(),
        symbol.to_string(),
        Direction::Down,
    );
    
    // 添加CCI信号
    let signal = Signal::new(
        "日线".to_string(),
        "CCI".to_string(),
        "空头".to_string(),
        "空头".to_string(),
        "其他".to_string(),
        "其他".to_string(),
        50,
    );
    
    pos.add_signal(signal);
    pos
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_position_creation() {
        let mut pos = Position::new(
            "测试策略".to_string(),
            "000001.SZ".to_string(),
            Direction::Up,
        );
        
        assert_eq!(pos.name, "测试策略");
        assert_eq!(pos.code, "000001.SZ");
        assert_eq!(pos.direction, Direction::Up);
        assert_eq!(pos.weight, 1.0);
        assert!(pos.enabled);
    }
    
    #[test]
    fn test_position_signal_management() {
        let mut pos = Position::new(
            "测试策略".to_string(),
            "000001.SZ".to_string(),
            Direction::Up,
        );
        
        let signal = Signal::new(
            "日线".to_string(),
            "测试信号".to_string(),
            "测试信号".to_string(),
            "多头".to_string(),
            "100".to_string(),
            "强信号".to_string(),
            80,
        );
        
        pos.add_signal(signal);
        
        assert_eq!(pos.signals.len(), 1);
        assert_eq!(pos.unique_signals.len(), 1);
        assert_eq!(pos.unique_signals[0], "测试信号");
    }
}